/**
 * 医疗空间数字孪生 - 设计系统工具函数
 * 提供设计系统相关的实用工具函数
 */

import type { CSSVariable, ThemeConfig, ResponsiveValue, Breakpoint } from './types';

/**
 * 获取CSS自定义属性的值
 */
export function getCSSVariable(variable: CSSVariable): string {
  if (typeof window === 'undefined') return '';
  return getComputedStyle(document.documentElement).getPropertyValue(variable).trim();
}

/**
 * 设置CSS自定义属性的值
 */
export function setCSSVariable(variable: CSSVariable, value: string): void {
  if (typeof window === 'undefined') return;
  document.documentElement.style.setProperty(variable, value);
}

/**
 * 批量设置CSS自定义属性
 */
export function setCSSVariables(variables: Record<CSSVariable, string>): void {
  if (typeof window === 'undefined') return;
  Object.entries(variables).forEach(([variable, value]) => {
    document.documentElement.style.setProperty(variable as CSSVariable, value);
  });
}

/**
 * 生成类名字符串，过滤掉falsy值
 */
export function cn(...classes: (string | undefined | null | false)[]): string {
  return classes.filter(Boolean).join(' ');
}

/**
 * 响应式值解析器
 */
export function getResponsiveValue<T>(
  value: T | ResponsiveValue<T>,
  currentBreakpoint: Breakpoint
): T {
  if (typeof value !== 'object' || value === null) {
    return value as T;
  }

  const responsiveValue = value as ResponsiveValue<T>;
  const breakpointOrder: Breakpoint[] = ['xs', 'sm', 'md', 'lg', 'xl'];
  const currentIndex = breakpointOrder.indexOf(currentBreakpoint);

  // 从当前断点开始向下查找可用值
  for (let i = currentIndex; i >= 0; i--) {
    const bp = breakpointOrder[i];
    if (responsiveValue[bp] !== undefined) {
      return responsiveValue[bp] as T;
    }
  }

  // 如果没有找到，返回第一个可用值
  for (const bp of breakpointOrder) {
    if (responsiveValue[bp] !== undefined) {
      return responsiveValue[bp] as T;
    }
  }

  throw new Error('No responsive value found');
}

/**
 * 获取当前断点
 */
export function getCurrentBreakpoint(): Breakpoint {
  if (typeof window === 'undefined') return 'md';

  const width = window.innerWidth;
  
  if (width >= 1920) return 'xl';
  if (width >= 1280) return 'lg';
  if (width >= 960) return 'md';
  if (width >= 600) return 'sm';
  return 'xs';
}

/**
 * 监听断点变化
 */
export function watchBreakpoint(callback: (breakpoint: Breakpoint) => void): () => void {
  if (typeof window === 'undefined') return () => {};

  let currentBreakpoint = getCurrentBreakpoint();
  
  function handleResize() {
    const newBreakpoint = getCurrentBreakpoint();
    if (newBreakpoint !== currentBreakpoint) {
      currentBreakpoint = newBreakpoint;
      callback(newBreakpoint);
    }
  }

  window.addEventListener('resize', handleResize);
  
  // 返回清理函数
  return () => window.removeEventListener('resize', handleResize);
}

/**
 * 主题切换工具
 */
export const theme = {
  /**
   * 切换到暗色模式
   */
  setDark(): void {
    if (typeof window === 'undefined') return;
    document.documentElement.classList.add('dark');
    localStorage.setItem('theme', 'dark');
  },

  /**
   * 切换到亮色模式
   */
  setLight(): void {
    if (typeof window === 'undefined') return;
    document.documentElement.classList.remove('dark');
    localStorage.setItem('theme', 'light');
  },

  /**
   * 设置自动模式（跟随系统）
   */
  setAuto(): void {
    if (typeof window === 'undefined') return;
    localStorage.setItem('theme', 'auto');
    this.applySystemTheme();
  },

  /**
   * 应用系统主题
   */
  applySystemTheme(): void {
    if (typeof window === 'undefined') return;
    const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    if (isDark) {
      document.documentElement.classList.add('dark');
    } else {
      document.documentElement.classList.remove('dark');
    }
  },

  /**
   * 获取当前主题
   */
  getCurrent(): 'light' | 'dark' | 'auto' {
    if (typeof window === 'undefined') return 'light';
    return (localStorage.getItem('theme') as 'light' | 'dark' | 'auto') || 'auto';
  },

  /**
   * 初始化主题
   */
  init(): void {
    if (typeof window === 'undefined') return;
    
    const savedTheme = this.getCurrent();
    
    if (savedTheme === 'dark') {
      this.setDark();
    } else if (savedTheme === 'light') {
      this.setLight();
    } else {
      this.applySystemTheme();
      // 监听系统主题变化
      window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
        if (this.getCurrent() === 'auto') {
          this.applySystemTheme();
        }
      });
    }
  },

  /**
   * 切换主题
   */
  toggle(): void {
    const current = this.getCurrent();
    if (current === 'light') {
      this.setDark();
    } else {
      this.setLight();
    }
  }
};

/**
 * 颜色工具
 */
export const color = {
  /**
   * 将hex颜色转换为RGB
   */
  hexToRgb(hex: string): { r: number; g: number; b: number } | null {
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? {
      r: parseInt(result[1], 16),
      g: parseInt(result[2], 16),
      b: parseInt(result[3], 16)
    } : null;
  },

  /**
   * 将RGB转换为hex
   */
  rgbToHex(r: number, g: number, b: number): string {
    return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
  },

  /**
   * 生成带透明度的颜色值
   */
  withOpacity(color: string, opacity: number): string {
    const rgb = this.hexToRgb(color);
    if (!rgb) return color;
    return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${opacity})`;
  },

  /**
   * 获取颜色的亮度（0-255）
   */
  getLuminance(hex: string): number {
    const rgb = this.hexToRgb(hex);
    if (!rgb) return 0;
    return Math.round(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b);
  },

  /**
   * 判断颜色是否为暗色
   */
  isDark(hex: string): boolean {
    return this.getLuminance(hex) < 128;
  }
};

/**
 * 间距工具
 */
export const spacing = {
  /**
   * 获取间距值
   */
  get(value: number): string {
    return getCSSVariable(`--space-${value}` as CSSVariable);
  },

  /**
   * 计算响应式间距
   */
  responsive(values: ResponsiveValue<number>): string {
    const currentBreakpoint = getCurrentBreakpoint();
    const value = getResponsiveValue(values, currentBreakpoint);
    return this.get(value);
  }
};

/**
 * 动画工具
 */
export const animation = {
  /**
   * 创建弹性动画
   */
  spring: {
    gentle: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
    wobbly: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
    stiff: 'cubic-bezier(0.35, 0.17, 0.3, 0.86)'
  },

  /**
   * 创建淡入动画
   */
  fadeIn(duration = 200): string {
    return `opacity 0 1 ${duration}ms ease-in`;
  },

  /**
   * 创建滑入动画
   */
  slideIn(direction: 'up' | 'down' | 'left' | 'right', duration = 300): string {
    const transforms = {
      up: 'translateY(20px)',
      down: 'translateY(-20px)',
      left: 'translateX(20px)',
      right: 'translateX(-20px)'
    };
    
    return `transform ${transforms[direction]} translateY(0) ${duration}ms ease-out`;
  }
};

/**
 * 媒体查询工具
 */
export const media = {
  /**
   * 生成媒体查询字符串
   */
  above(breakpoint: Breakpoint): string {
    const breakpoints = {
      xs: '0px',
      sm: '600px',
      md: '960px',
      lg: '1280px',
      xl: '1920px'
    };
    return `@media (min-width: ${breakpoints[breakpoint]})`;
  },

  /**
   * 生成向下的媒体查询
   */
  below(breakpoint: Breakpoint): string {
    const breakpoints = {
      xs: '599px',
      sm: '959px',
      md: '1279px',
      lg: '1919px',
      xl: '2559px'
    };
    return `@media (max-width: ${breakpoints[breakpoint]})`;
  },

  /**
   * 检查是否为移动设备
   */
  isMobile(): boolean {
    if (typeof window === 'undefined') return false;
    return window.innerWidth < 960;
  },

  /**
   * 检查是否支持触摸
   */
  isTouch(): boolean {
    if (typeof window === 'undefined') return false;
    return 'ontouchstart' in window || navigator.maxTouchPoints > 0;
  }
};

/**
 * 可访问性工具
 */
export const a11y = {
  /**
   * 生成唯一ID
   */
  generateId(prefix = 'id'): string {
    return `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
  },

  /**
   * 检查是否启用了减少动画
   */
  prefersReducedMotion(): boolean {
    if (typeof window === 'undefined') return false;
    return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  },

  /**
   * 检查是否使用键盘导航
   */
  isKeyboardUser(): boolean {
    if (typeof window === 'undefined') return false;
    // 简单的键盘用户检测
    return document.body.classList.contains('keyboard-user');
  },

  /**
   * 设置焦点陷阱
   */
  trapFocus(container: HTMLElement): () => void {
    const focusableElements = container.querySelectorAll(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    );
    
    const firstFocusable = focusableElements[0] as HTMLElement;
    const lastFocusable = focusableElements[focusableElements.length - 1] as HTMLElement;

    function handleKeyDown(e: KeyboardEvent) {
      if (e.key === 'Tab') {
        if (e.shiftKey) {
          if (document.activeElement === firstFocusable) {
            e.preventDefault();
            lastFocusable.focus();
          }
        } else {
          if (document.activeElement === lastFocusable) {
            e.preventDefault();
            firstFocusable.focus();
          }
        }
      }
    }

    container.addEventListener('keydown', handleKeyDown);
    firstFocusable?.focus();

    return () => container.removeEventListener('keydown', handleKeyDown);
  }
};

/**
 * 性能优化工具
 */
export const performance = {
  /**
   * 防抖函数
   */
  debounce<T extends (...args: any[]) => any>(
    func: T,
    wait: number
  ): (...args: Parameters<T>) => void {
    let timeout: ReturnType<typeof setTimeout>;
    return (...args: Parameters<T>) => {
      clearTimeout(timeout);
      timeout = setTimeout(() => func(...args), wait);
    };
  },

  /**
   * 节流函数
   */
  throttle<T extends (...args: any[]) => any>(
    func: T,
    limit: number
  ): (...args: Parameters<T>) => void {
    let inThrottle: boolean;
    return (...args: Parameters<T>) => {
      if (!inThrottle) {
        func(...args);
        inThrottle = true;
        setTimeout(() => inThrottle = false, limit);
      }
    };
  },

  /**
   * 请求动画帧节流
   */
  rafThrottle<T extends (...args: any[]) => any>(func: T): (...args: Parameters<T>) => void {
    let rafId: number;
    return (...args: Parameters<T>) => {
      if (rafId) return;
      rafId = requestAnimationFrame(() => {
        func(...args);
        rafId = 0;
      });
    };
  }
};

/**
 * 验证工具
 */
export const validation = {
  /**
   * 验证颜色值
   */
  isValidColor(color: string): boolean {
    const s = new Option().style;
    s.color = color;
    return s.color !== '';
  },

  /**
   * 验证CSS单位
   */
  isValidCSSUnit(value: string): boolean {
    return /^-?\d*\.?\d+(px|em|rem|%|vh|vw|vmin|vmax)?$/.test(value);
  },

  /**
   * 验证断点
   */
  isValidBreakpoint(breakpoint: string): breakpoint is Breakpoint {
    return ['xs', 'sm', 'md', 'lg', 'xl'].includes(breakpoint);
  }
}; 